package Z11_11_atomic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author： pang-yun
 * @date： 2021-11-11 15:49
 * 功能目的 ：用于  原子数组  可以保护 数组内的结果
 */

public class AtomicArray {
    public static void main(String[] args) {
        util(
                () -> new int[10],
                (t) -> t.length,
                (t, index) -> t[index]++,
                t -> System.out.println(Arrays.toString(t))

        );
        //[9896, 9896, 9889, 9875, 9873, 9876, 9878, 9868, 9883, 9906]

        util(
                () -> new AtomicIntegerArray(10),
                (t) -> t.length(),
                (t, index) -> t.getAndIncrement(index),
                t -> System.out.println(t)
        );
        //[10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000]
    }

    /**
     * @param arraySupplier supplier 提供者  无中生有 ()-> 结果
     * @param lengthFunc    function  一个参数 得到一个结果  （参数） 结果  BiFunction(参数1， 参数2)  结果
     * @param consumer      consumer 消费者
     * @param printConsumer
     * @param <T>
     */
    private static <T> void util(
            Supplier<T> arraySupplier,
            Function<T, Integer> lengthFunc,
            BiConsumer<T, Integer> consumer,
            Consumer<T> printConsumer
    ) {
        ArrayList<Thread> threads = new ArrayList<>();
        T t = arraySupplier.get();
        Integer length = lengthFunc.apply(t);
        for (int i = 0; i < length; i++) {
            //每个线程 对数组 做 10000 次操作
            threads.add(new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    consumer.accept(t, j % length);
                }
            }));
        }
        //启动所有线程
        threads.forEach(thread -> thread.start());
        // 等待所有线程结束
        threads.forEach(thread -> {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        printConsumer.accept(t);

    }
}
